<?php

/**
*Form Builder & Admin Generator

*@author marcio <opi14@op.pl>, <polishvodka7@gmail.com>
*@copyright Copyright (c) 2011, marcio
*@version 1.6.5
*/

require_once('Form_Builider.php');
require_once('libraries/Db.php');
require_once('libraries/Loader.php');
require_once('libraries/Acl.php');
require_once('libraries/Auth.php');
require_once('libraries/User.php');
require_once('libraries/View.php');
require_once('libraries/Panel.php');
require_once('libraries/Security.php');
require_once('libraries/Exception.php');

class Volta_Admin_Generator
{
	
	/**
	*Skladowa klasy ktora przechowywuje instacje klasy do obslugi mysql
	*@var object $db
	*@access private
	*/
	private $db;
	
	/**
	*Skladowa klasy ktora przechowywuje instacje klasy do obslugi formularzy
	*@var object $form_builider
	*@access private
	*/
	private $form_builider;
	
	/**
	*Skladowa klasy ktora przechowywuje nazwe tabeli dla ktorej ma wygenerowac PA
	*@var string $table
	*@access protected
	*/
	protected $table;
	
	/**
	*Skladowa klasy ktora przechowywuje dane z tabeli
	*@var array $records
	*@access protected
	*/
	protected $records = array();
	
	/**
	*Skladowa klasy ktora przechowywuje nazwy wszystkich kolumn z tabeli
	*@var array $columns
	*@access protected
	*/
	protected $columns = array();
	
	/**
	*Skladowa klasy ktora przechowywuje nazwy kolumn ktora maja byc wyswietlane w PA
	*@var array $allowed_columns
	*@access protected
	*/
	protected $allowed_columns = array(
										'id',
										'tytul',
										'data',
										'autor'
	                                  );
				
	/**
	*Skladowa klasy ktora przechowywuje akcje dla PA
	*@var array $actions
	*@access protected
	*/				
	protected $actions = array(
	                             'delete' => array('Usun', 'img/delete.png'),
							     'update' => array('Edytuj', 'img/edit.png')
	                          );
					
	/**
	*Skladowa klasy ktora przechowywuje reguly walidacji
	*@var array $validation_rules
	*@access protected
	*/					
	protected $validation_rules = array(	

	                                  );
	
	/**
	*Skladowa klasy ktora przechowywuje glowna kolumna na podstawie ktorej wykonywane sa wszystkie akcje
	*@var string $where_col
	*@access protected
	*/	
	protected $where_col = 'id';
		
	/**
	*Skladowa klasy ktora przechowywuje primary key dla relacji
	*@var string $where_col_rel
	*@access protected
	*/	
	protected $where_col_rel = 'id';
		
	/**
	*Skladowa klasy ktora ustawia czy PA ma zawierac przycisk nowego rekordu
	*@var bool $new_action
	*@access protected
	*/						
	protected $new_action = true;
	
	/**
	*Skladowa klasy ktora przechowywuje czy mod_rewrite jest on/off
	*@var bool $nice_urls
	*@access protected
	*/	
	protected $nice_urls = false;
	
	/**
	*Skladowa klasy ktora przechowywuje ustawieniai info dotyczace stronnicowania
	*@var array $paginate
	*@access protected
	*/	
	protected $paginate = array(
							  'per_page' => 3,
							  'count' => 0,
							  'pages' => 0,
							  'current' => 0,
							  'next' => 0,
							  'prev' => 0,
							  'first' => 1,
							  'last' => 0
	                         );
				
	/**
	*Skladowa klasy ktora przechowywuje nazwe wykonywanej akcji
	*@var string $do_action
	*@access protected
	*/					
	protected $do_action;
	
	/**
	*Skladowa klasy ktora przechowywuje tresc bledow dla akcji
	*@var array $err_code
	*@access protected
	*/	
	protected $err_code = array(
								100 => 'Obiekt zostal usuniety',
								101 => 'Wystapil blad podczas usuwania obiektu',
								200 => 'Usuwanie powiodlo sie',
								201 => 'Wystapil blad podczas usuwania',
								202 => 'Nie zaznoczono zadnych rekordow',
								300 => 'Edytowano rekord',
								301 => 'Wystapil blad podczas edycji rekordu',
								400 => 'Dodanie rekordu powiodlo sie',
								401 => 'Wystapil blad podczas dodawania rekordu'
								);
				
	/**
	*Skladowa klasy ktora przechowywuje atrybuty dla danego pola
	*@var array $attributes
	*@access protected
	*/					
	protected $attributes;
	
	/**
	*Skladowa klasy ktora przechowywuje wartosci dla danego pola
	*@var array $values
	*@access protected
	*/	
	protected $values = array();
	
	/**
	*Skladowa klasy ktora przechowywuje info na temat relacji pomiedzy tabelami
	*@var array $relation
	*@access protected
	*/	
	protected $relation = array();
	
	/**
	*Skladowa klasy ktora przechowywuje typ kolumny w html
	*@var array $form_element
	*@access protected
	*/
	protected $form_element = array();
	
	/**
	*Gdy ustawione na built-in formularze wyswietlaja sie w normalny sposob w przeciwnym wypadku za pomoca widokow
	*@var string $render_form_view
	*@access protected
	*/
	protected $render_form_view = 'built-in';
	
	/**
	*Gdy ustawione na built-in panel wyswietla sie w sposob generowany przez klase
	*@var string $render_panel_view
	*@access protected
	*/
	protected $render_panel_view = 'built-in';
	
	/**
	*Tresc powiadomienia dla panelu
	*@var string $panel_message
	*@access protected
	*/
	protected $panel_message = '';
	
	/**
	*Istacja klasy panel view
	*@var null|object	$render_panel_view
	*@access private
	*/
	private $panel_view_object = null;
	
	/**
	*Istacja klasy Security
	*@var null|object	$security
	*@access private
	*/
	protected $security = null;
	
								
	/**
	*Inicjalizuje wszystko, razem ze stronnicowaniem
	*@access public 
	*@param string $table nazwa tabeli zbazy
	*/
	public function __construct($table)
	{
		$this -> security = new Volta_Security();
		$this -> security -> filter_vars(true,true);
	
		if(!is_string($table))
			throw new InvalidArgumentException('Podany argument do konstruktora nie jest stringiem');
	
		$this -> db = Db::Factory("MySql");
		$this -> table = $table;
		
		$start = (isset($_GET['page'])) ? (int)$_GET['page'] : 1;
		$order = (isset($_GET['sort'])) ? $_GET['sort'] : $this -> where_col;
		
		if($start <= 1)
			$offset = 0;
		else
			$offset = ($start -1) * $this -> paginate['per_page'];
			
		$count = $this -> db -> Select('*', $this -> table, 'COUNT', true)
					   -> Execute();

		$tab = $this -> db -> FetchAssoc($count);
		$this -> paginate['count'] = $tab['var'];
		
		$data = $this -> db -> Select('*', $table)
					  -> OrderBy($order, 'desc')
                   	  -> Limit(array($offset, $this -> paginate['per_page']))
					  -> Execute();
					  
		if($this -> db -> CountRows($data) == 0)
			throw new Volta_Admin_Generator_NoRows_Exception('Brak rekordow');
					  
		$this -> records =  $this -> db -> FetchAllAssoc($data);
		
		if(sizeof($this -> records) > 0)
			$this -> columns = array_keys($this -> records[0]);
	}
	
	/**
	*Ustawia atrybuty patrz Volta_Form_Builider -> __call()
	*@access public 
	*@param string $name nazwa i atrybut pola
	*@param string $args wartosc atrybutu
	*
	*$instance -> set_login_value('Podaj login');
	*/
	public function __call($name, $args)
	{
		$explode = explode('_', $name);
		
		if($explode[0] == 'set')
		{
			$this -> attributes[$explode[1]] = array($explode[2] => $args[0]);
		}
	}
	
	/**
	*ustawiamy relacje jeden do jednego
	*@access public 
	*@param string $table nazwa tabeli z bazy z ktorej chcemy pobrac dane
	*@param string $table_foreign_key nazwa obcego klucza ktory jest potrzebny do relacji tabel
	*@return array $data zwraca nam tablice z rekordami
	*/
	public function relationship_one_to_one($table, $table_foreign_key)
	{
		if(!is_string($table) || !is_string($table_foreign_key))
			throw new InvalidArgumentException('Wymagane argumenty musza byc typu string');
			
		$this -> relation['table'] = $table;
		$this -> relation['foreign_key'] = $table_foreign_key;
		
		$relation_data = $this -> db -> Select('*', $this -> relation['table'])
							   -> Where(array($this -> relation['foreign_key'] => $_GET[$this -> where_col_rel]))
							   -> Limit(1)
							   -> Execute();
							   
		$data = $this -> db -> FetchAllAssoc($relation_data);
		
		if(sizeof($data) > 0)
			$this -> relation['columns'] = array_keys($data[0]);
		
		return $data;
	}
	
	/**
	*ustawiamy relacje jeden do wielu
	*@access public 
	*@param string $table nazwa tabeli z bazy z ktorej chcemy pobrac dane
	*@param string $table_foreign_key nazwa obcego klucza ktory jest potrzebny do relacji tabel
	*@param string $order kolumna po ktorej maja byc sortowane rekordy
	*@return array $data zwraca nam tablice z rekordami
	*/
	public function relationship_one_to_many($table, $table_foreign_key, $order = 'id')
	{
		if(!is_string($table) || !is_string($table_foreign_key) || !is_string($order))
			throw new InvalidArgumentException('Wymagane argumenty musza byc typu string');
			
		$this -> relation['table'] = $table;
		$this -> relation['foreign_key'] = $table_foreign_key;
		
		$relation_data = $this -> db -> Select('*', $this -> relation['table'])
							   -> Where(array($this -> relation['foreign_key'] => $_GET[$this -> where_col_rel]))
							   -> OrderBy($order, 'desc')
							   -> Execute();
							   
		$data = $this -> db -> FetchAllAssoc($relation_data);

		if(sizeof($data) > 0)
			$this -> relation['columns'] = array_keys($data[0]);

		return $data;
	}
	
	/**
	*ustawiamy relacje wiele do wielu
	*@access public 
	*@param string $from_table nazwa tabeli z bazy z ktorej chcemy pobrac dane
	*@param array $columns lista kolumn ktore potrzebujemy
	*@param array $relations lista relacji w postaci tablicy klucz to pierwsza kolumna = druga kolumna klauzula ON()
	*@param string $join typ relacji tabel inner/left/right/outer
	*@return array $data zwraca nam tablice z rekordami
	*/
	//array('comment' => array('comment.news_id', 'news.id'));
	//$instance -> relationship_many_to_many('users', array('users.name', 'group.name'), array('comment.news_id' => 'news.id'))
	public function relationship_many_to_many($from_table, $columns, $relations, $join = 'INNER')
	{
		if(!is_array($relations))
			throw new InvalidArgumentException('Wymagany argument musi byc tablica');
			
		$this -> db -> Select($columns, $from_table);
		
		foreach($relations as $join_table => $on_condition)
			$this -> db-> Join($join_table, $on_condition, $join);
				
		$relation_data = $this -> db -> Execute();
							   
		$data = $this -> db -> FetchAllAssoc($relation_data);
		
		if(sizeof($data) > 0)
			$this -> relation['columns'] = array_keys($data[0]);
		
		return $data;
	}
	
	/**
	*ustawiamy nazwy kolumn do wyswietlenia w panelu relacji
	*@access public 
	*@param string $columns lista kolumn ktore maja byc wywietlane w panelu relacji
	*/
	public function set_relationship_allowed_columns($columns)
	{
		if(!is_array($columns))
			throw new InvalidArgumentException('Wymagany argument musi byc tablica');
			
		foreach($columns as $column)
			$this -> relation['allowed_columns'][] = $column;
	}
	
	/**
	*usuwamy rekordy ktory maja relacje z aktualnie usuwanym rekordem
	*@access protected
	*@return bool
	*/
	protected function relationship_delete_table()
	{
		if($this -> db -> Delete($this -> relation['table'], array($this -> relation['foreign_key']  => $_GET[$this -> where_col])))
			return true;
		return false;
	}
	
	/**
	*Wyswietla panel relacji
	*@access public 
	*@param array $records tablice rekordow
	*@return string $panel kod html panelu relacji
	*/
	public function show_panel_relationship($records)
	{
		if(sizeof($records) == 0)
			return 'Nie znaleziony zadnych powiazanych rekordow';
		
		$panel .= '<form method="post">
				   <table align="center" style="border:3px solid #000000;"><tr><td>
		           <table align="right"><tr>';
		
		$panel .= '<td>
		<input type="submit" name="del_checked" value="Usun zaznaczone"></td></tr></table></td></tr><tr><td>';
		$panel .= '<table align="center" cellpadding="3" cellspacing="0">';
		$panel .= '<tr>';
		
		foreach($this -> relation['columns'] as $column)
		{
			if(in_array($column, $this -> relation['allowed_columns']))
				$panel .= '<td align="center" style="padding:2px;background-color:#8B0000;font-weight:bold;">'.$column.'</td>';
		}
		
		$panel .= '<td align="center"style="background-color:#8B0000;font-weight:bold;">Akcje</td>';
		$panel .= '</tr>';
		
		$i = 0;
		
		foreach($records as $record)
		{
			
			if($i % 2 == 0)
				$color = '#778899';
			else
				$color = '#C0C0C0';
		
			$panel .= '<tr style="background-color:'.$color.';">';
			
			foreach($record as $column => $data)
				if(in_array($column, $this -> relation['allowed_columns']))
					$panel .= '<td>'.$data.'</td>';
				
			$panel .= '<td>';
				
			foreach($this -> actions as $action => $description)
			{
				$panel .= '<a href="?action='.$action.'_'.$this -> relation['table'].'&id='.$record['id'].'">';

				if(sizeof($description) > 0)
					$panel .= '<img src="'.$description[1].'" alt="'.$description[0].'">';
				else
					$panel .= '<input type="button" value="'.$description.'">';
						   
				$panel .= '</a>';	
			}
			
			$panel .= '<input type="checkbox" value="'.$record['id'].'" name="del[]"';
			$panel .= '</td></tr>';
			
			$i++;
		}
		
		$panel .= '</table></td></tr></table></form>';
		
		return $panel;
	}
	
	/**
	*Ustawia ile rekorodow ma byc na kazdej stronie
	*@access public 
	*@param integer $per_page ilosc rekordow
	*/
	public function set_per_page($per_page)
	{
		if(!is_int($per_page))
			throw new InvalidArgumentException('Wymagany argument musi byc typu integer');
		
		$this -> paginate['per_page'] = $per_page;
	}
	
	/**
	*Ustawia czy ma byc przycisk do dodawania nowego rekordu
	*@access public 
	*@param bool $on gdy true mamy przycisk
	*/
	public function set_new_action($on = false)
	{
		if(!is_bool($on))
			throw new InvalidArgumentException('Wymagany argument true/false');
			
		$this -> new_action = $on;
	}
	
	/**
	*Ustawia kolumne za pomoca ktorej ma byc ustalane ktory rekord ma byc usuwany/edytowany
	*@access public 
	*@param string $column nazwa kolumny (primary key i unique)
	*/
	public function set_where_column($column)
	{
		if(!is_string($column))
			throw new InvalidArgumentException('Wymagany argument musi byc typu string');
			
		$this -> where_col = $column;
	}
	
	/**
	*Ustawia kolumne za pomoca ktorej maja byc ustawione relacje
	*@access public 
	*@param string $column nazwa kolumny (primary key i unique)
	*/
	public function set_where_rel_column($column)
	{
		if(!is_string($column))
			throw new InvalidArgumentException('Wymagany argument musi byc typu string');
			
		$this -> where_col_rel = $column;
	}
	
	/**
	*Ustawia akcje dla panelu
	*@access public 
	*@param array $action tablice z akcjami
	*
	*gdy mamy podany path to zamiast prostego buttona mamy <img src="">
	*$instance -> set_actions(array('nazwa_akcji' => array('opis_akcji' => 'path')));
	*/
	public function set_actions(array $action)
	{
		if(is_array($action))
			array_push($this -> actions, $action);
		else
			throw new InvalidArgumentException('Wymagany argument musi byc tablica');
	}
	
	/**
	*Usuwamy dana akcje
	*@access public 
	*@param string $action nazwa akcji
	*/
	public function delete_action($action)
	{
		if(array_key_exists($action, $this -> actions))
			unset($this -> actions[$action]);
	}
	
	/**
	*Ustawia czy mod rewrite jest wlaczone lub nie by tworzyc dobrze linki itp..itd..
	*@access public 
	*@param bool $mod_rewrite
	*/
	public function set_nice_urls($mod_rewrite = true)
	{
		if(!is_bool($mod_rewrite))
			throw new InvalidArgumentException('Wymagany argument musi typu boolean');
			
		else
			$this -> nice_urls = $mod_rewrite;
	}
	
	/**
	*Ustawia widok formularzy
	*@access public 
	*@param string $view nazwa widoku
	*/
	public function set_render_form_view($view)
	{
		if(!is_string($view))
			throw new InvalidArgumentException('Wymagany argument musi typu string');
			
		else
			$this -> render_form_view = $view;
	}
	
	/**
	*Ustawia widok panelu
	*@access public 
	*@param string $view nazwa widoku
	*/
	public function set_render_panel_view($view)
	{
		if(!is_string($view))
			throw new InvalidArgumentException('Wymagany argument musi typu string');
			
		else
			$this -> render_panel_view = $view;
	}
	
	/**
	*Dodaje kolumny ktore sa wyswietlane w panelu dla danej tabeli
	*@access public 
	*@param string|array $column nazwa kolumny
	*/
	public function add_allowed_column($column)
	{
		if(is_array($column))
			foreach($column as $col_name)
				$this -> allowed_columns[] = $col_name;
		
		else
			$this -> allowed_columns[] = $column;
	}
	
	/**
	*Dodajemy reguly walidacji dla danego pola patrz Volta_Form_Builider -> add_rules();
	*@access public 
	*@param array $rules regula
	*/
	public function add_validation_rules($field, $rules) 
	{
		if(sizeof($rules) > 1)
			if(array_key_exists($field, $this -> validation_rules))
				array_push($this -> validation_rules[$field], array($field => array($rules)));
			else
				array_push($this -> validation_rules, array($field => array($rules)));
		else
			$this -> validation_rules = array($field => array($rules));
	}
	
	/**
	*See Volta_Form_Builider -> set_equivalent()
	*@access public 
	*@param string $field
	*@param string $type
	*/
	public function set_form_element($field, $type) 
	{
		$data = $this -> get_schema($_GET['action']);

		if(array_key_exists($field, $data[0]))
			$this -> form_element[$field] = $type;
	}
	
	/**
	*See Volta_Form_Builider -> set_equivalent()
	*@access public 
	*/
	protected function set_equivalent() 
	{
		foreach($this -> form_element as $field => $type)
			$this -> form_builider -> set_equivalent($field, $type);
	}
	
	/**
	*Dodajemy dodatkowe wartosc dla danego pola przydatne dla checkbox/radio/menu
	*@access public 
	*@param string $field nazwa pola ktore chcemy rozszerzyc
	*@param string|array $values wartosci
	*/
	public function add_values($field, $values)
	{
		$this -> values[$field] = array_merge((array)$this -> values[$field], (array)$values);
	}
	
	/**
	*Generuje panel wraz z akcjami
	*@access protected 
	*@return string kod html panelu
	*/
	protected function show_action_panel()
	{
	
		$panel .= '<form method="post">
				   <table align="center" style="border:3px solid #000000;"><tr><td>
		           <table align="right"><tr>';
	
		if($this -> new_action)
		{
			$panel .= '<td><a href="?action=create_'.$this -> table.'">
					   <input type="button" value="Nowy">
					   </a></td>';
		}
		
		$panel .= '<td>
		<input type="submit" name="del_checked" value="Usun zaznaczone"></td></tr></table></td></tr><tr><td>';
		$panel .= '<table align="center" cellpadding="3" cellspacing="0">';
		$panel .= '<tr>';
		
		foreach($this -> columns as $column)
		{
			if(in_array($column, $this -> allowed_columns))
				$panel .= '<td align="center" style="padding:2px;background-color:#8B0000;font-weight:bold;">'.$column.'</td>';
		}
		
		$panel .= '<td align="center"style="background-color:#8B0000;font-weight:bold;">Akcje</td>';
		$panel .= '</tr>';
		
		$i = 0;
		
		foreach($this -> records as $record)
		{
			
			if($i % 2 == 0)
				$color = '#778899';
			else
				$color = '#C0C0C0';
		
			if(sizeof($this -> relation) > 0)
				$js = 'onclick="window.location.href=\'?relationship='.$this -> table.'&'.$this -> where_col_rel.'='.$record[$this -> where_col_rel].'\'"';
			
			$panel .= '<tr style="background-color:'.$color.';">';
			
			foreach($record as $column => $data)
				if(in_array($column, $this -> allowed_columns))
					$panel .= '<td '.$js.'>'.$data.'</td>';
				
			$panel .= '<td>';
				
			foreach($this -> actions as $action => $description)
			{
				$panel .= '<a href="?action='.$action.'_'.$this -> table.'&'.$this -> where_col.'='.$record[$this -> where_col].'">';

				if(sizeof($description) > 0)
					$panel .= '<img src="'.$description[1].'" alt="'.$description[0].'">';
				else
					$panel .= '<input type="button" value="'.$description.'">';
						   
				$panel .= '</a>';	
			}
			
			$panel .= '<input type="checkbox" value="'.$record['id'].'" name="del[]"';
			$panel .= '</td></tr>';
			
			$i++;
		}
		
		$panel .= '</table></td></tr></table></form>';
		
		return $panel;
	}
	
	/**
	*Generuje panel wraz z akcjami z odpowiednim widokiem
	*@access public
	*@return string kod html panelu
	*/
	public function render_panel()
	{
		if($this -> render_panel_view == 'built-in')
			return $this -> show_action_panel();
		else
		{
			$cfg['actions'] = $this -> actions;
			$cfg['new_action'] = $this -> new_action;
			$cfg['relation'] = $this -> relation;
			$cfg['table'] = $this -> table;
			$cfg['where'] = $this -> where_col;
			$cfg['where_rel'] = $this -> where_col_rel;
		
			$this -> panel_view_object = new Volta_panel($this -> render_panel_view);
			$this -> panel_view_object -> get() -> configure($cfg);
			$this -> panel_view_object -> get() -> set_columns($this -> columns, $this -> allowed_columns);
			$this -> panel_view_object -> get() -> set_records($this -> records);
			$this -> panel_view_object -> get() -> set_message($this -> panel_message);
			
			return $this -> panel_view_object -> get() -> render();
		}
	}
	
	/**
	*Pobiera cale info o tabeli z jej edycja lub nie
	*@access protected
	*@return array zwraca nam tablice z danymi
	*/
	protected function get_schema($action)
	{
		$action = explode('_', $action);
		
		if($action[0] === 'update')
			$sql = $this -> db -> Select('*', $this -> get_table($action))
						 -> Where(array($this -> where_col => $_GET[$this -> where_col]))
						 -> Limit(1)
						 -> Execute();
		else
			$sql = $this -> db -> Select('*', $this -> get_table($action))
						 -> Limit(1)
						 -> Execute();
							  
	    return $this -> db -> FetchAllAssoc($sql);
	}
	
	/**
	*Tworzy instacje form builider'a z odpowiedim arg. dla konstruktora
	*@access protected
	*@param string $action ustawia instacje z edycja lub bez
	*@param array $data tablica z budowa tabeli
	*/
	protected function set_instance($action, $data)
	{
		if($action === 'update')
			$this -> form_builider = new Volta_Form_Builider($data, true);
		else
			$this -> form_builider = new Volta_Form_Builider($data);
	}
	
	/**
	*Ustawia wczesniej podana walidacje
	*@access protected
	*/
	protected function set_validation_rules()
	{
		foreach($this -> validation_rules as $key => $arr)
		{
			foreach($arr as $k => $rules)
			{
				foreach($rules as $validator => $rule)
				{
					if(array_key_exists($key, $this -> records[0]))
					{
						$this -> form_builider -> load_validators($validator);
						$this -> form_builider -> add_rules($key, new $validator($rule));
					}
				}
			}
		}
	}
	
	/**
	*ustawia wczensiej podane atrybuty dla poszczegolych pol
	*@access protected 
	*/
	protected function set_attributes()
	{
		if(sizeof($this -> attributes) > 0)
		{
			foreach($this -> attributes as $key => $f)
			{
				foreach($f as $attr => $value)
				{
					$func = 'set_'.$key.'_'.$attr;
					$this -> form_builider -> $func($value);
				}
			}
		}
	}
	
	/**
	*Zwraca nam nazwe aktualnie uzywanej tabeli
	*@access public 
	*@param string|array $action zmienna/tablica z info
	*@return string nazwa tabeli
	*/
	protected function get_table($action)
	{
		if(is_array($action) && sizeof($action) > 0)
		{
			unset($action[0]);
			$tbl = implode('_', $action);
		}
		
		else
			$tbl = $action;
				
		return ($tbl === $this -> relation['table']) ? $this -> relation['table'] : $this -> table;
	}	
	
	/**
	*Wykonuje wszystkie potrzebne czynnosci i gdy zachodzi taka potrzeba wykonuje podana akcje
	*@access public 
	*@return string|array zwraca blad w przypadku niepowiedzenia sie operacji lub msg ewentualnie error z walidacji
	*/
	public function execute_action()
	{
		if(!$this -> nice_urls)
		{
		
			$user = new Volta_User();
			$acl = new Volta_Acl();
			$auth = new Volta_Auth($user);
			
			$user -> get($_SESSION['user']);
			$acl -> set_user_role($user -> role, $user -> id);
			$acl -> load_rules();
		
			try
			{
				if($auth -> is_logged())
				{
			
					$this -> do_action = $_GET['action'];
					$action = explode('_', $_GET['action']);
					
					$acl_opt = $action;
					unset($acl_opt[0]);
					$role = $action[0];
					$resource = implode('_', $acl_opt);
			
					$data = $this -> get_schema($_GET['action']);
					$this -> set_instance($action[0], $data);
					$this -> set_equivalent();
			
					if(array_key_exists('data', $data[0]))
						$this -> form_builider -> set_data_value(date('d/m/Y'));
					else if(array_key_exists('date', $data[0]))
						$this -> form_builider -> set_date_value(date('d/m/Y'));
				
					$this -> set_validation_rules();	
					$this -> set_attributes();
					
					if(sizeof($this -> values) > 0)
					{
						//dodac defaultowe value nawet jesli nie edytujemy
						//dac to tylko do edit'a
						foreach($this -> values as $key => $field)
							$this -> form_builider -> add_values($key, $field);
					}
			
					if(!isset($_POST['submit_form_sbt']))
						$token = $this -> security -> csrf_token_generate();
			
					if($action[0] === 'delete')
					{
						$_POST['token'] = $token;
						
						try
						{
							if($acl -> is_allowed($resource, $role))
							{
								try
								{
									if($this -> security -> csrf_check_token())
									{
										if($this -> db -> Delete($this -> get_table($action), array($this -> where_col => $_GET[$this -> where_col])))
										{
											if($this -> relationship_delete_table())
											{
												if($this -> render_panel_view == 'built-in')
													return $this -> err_code[100];
												else
												{
													$this -> panel_message = $this -> err_code[100];
													header("Refresh: 1; URL=  index.php");
												}
											}
											
											else
											{
												if($this -> render_panel_view == 'built-in')
													return $this -> err_code[100];
												else
												{
													$this -> panel_message = $this -> err_code[101];
													header("Refresh: 1; URL=  index.php");
												}
											}
										}
									}
								}
								
								catch(Volta_Admin_Generator_Csrf_Exception $e)
								{
									if($this -> render_panel_view == 'built-in')
										return $e -> getMessage();
									else
										$this -> panel_message = $e -> getMessage();
								}
							}
						}
						
						catch(Volta_Acl_Deny_Exception $e)
						{
							if($this -> render_panel_view == 'built-in')
								return $e -> getMessage();
							else
								$this -> panel_message = $e -> getMessage();
						}
					}
					
					else if(isset($_POST['del_checked']))
					{
						$_POST['token'] = $token;
						try
						{
							if($this -> security -> csrf_check_token())
							{
								if(isset($_GET['relationship']))
									$table = $this -> relation['table'];
								else
									$table = $this -> table;
								
								if($acl -> is_allowed($table, 'delete'))
								{								
									if(sizeof($_POST['del']) >= 1)
									{
										foreach($_POST['del'] as $record => $id)
										{
											if($this -> db -> Delete($table, array($this -> where_col => $id)))
												$code = 200;
											else
												$code = 201;
										}
									}
								
									else
										$code = 202;
					
									if($this -> render_panel_view == 'built-in')
										return $this -> err_code[$code];
									else
									{
										$this -> panel_message = $this -> err_code[$code];
										header("Refresh: 1; URL=  index.php");
									}
								}
							}
						}
						
						catch(Volta_Admin_Generator_Csrf_Exception $e)
						{
							if($this -> render_panel_view == 'built-in')
								return $e -> getMessage();
							else
								$this -> panel_message = $e -> getMessage();
						}
						
						catch(Volta_Acl_Deny_Exception $e)
						{
							if($this -> render_panel_view == 'built-in')
								return $e -> getMessage();
							else
								$this -> panel_message = $e -> getMessage();
						}
					}
			
					else if($action[0] === 'update')
					{			
						try
						{
							if($acl -> is_allowed($resource, $role))
							{
							
								$table = $this -> get_table($action);
								
								$this -> form_builider -> add_field('token');
								$this -> form_builider -> set_token_value($token);
								$this -> form_builider -> add_form_action(array('action' => 'update_'.$table));
								
								if($this -> render_form_view == 'built-in')
									$view = $this -> form_builider -> create_form();
									
								else
								{
									$this -> form_builider -> render = false;
									$form = $this -> form_builider -> create_form();
									$view = new Volta_Views($this -> render_form_view, $form);
								}
								

								if(isset($_POST['submit_form_sbt']))
								{
									try
									{
										if($this -> security -> csrf_check_token())
										{
											$valid = $this -> form_builider -> validate();

											if(!is_array($valid))
											{
												$this -> security -> filter_vars(true,true);
									
												if($this -> form_builider -> save($table, array($this -> where_col => $_GET[$this -> where_col]), array("token")))
												{
													if($this -> render_form_view === 'built-in')
														return $this -> err_code[300];
													else
													{
														$view -> set_message($this -> err_code[300]);
														header("Refresh: 1; URL = index.php");
													}
												}
									
												else 
												{
													if($this -> render_form_view === 'built-in')
														return $this -> err_code[301];
													else
													{
														$view -> set_message($this -> err_code[301]);
														header("Refresh: 2; URL=  index.php");
													}
												}	
											}
					
											else
											{
												if($this -> render_form_view == 'built-in')
													return $valid;
												else
													$view -> set_errors($valid);
											}
										}
									}
									
									catch(Volta_Admin_Generator_Csrf_Exception $e)
									{
										if($this -> render_panel_view == 'built-in')
											return $e -> getMessage();
										else
											$this -> panel_message = $e -> getMessage();
									}
								}
								
								return $view;
							}
						}
						
						catch(Volta_Acl_Deny_Exception $e)
						{
							if($this -> render_panel_view == 'built-in')
								return $e -> getMessage();
							else
								$this -> panel_message = $e -> getMessage();
						}
					}
			
					else if($action[0] === 'create')
					{	
						try
						{
							if($acl -> is_allowed($resource, $role))
							{
							
								$this -> form_builider -> add_field('token');
								$this -> form_builider -> set_token_value($token);
								$this -> form_builider -> add_form_action(array('action' => 'create_'.$this -> table));
								
								if($this -> render_form_view == 'built-in')
									$view = $this -> form_builider -> create_form();
									
								else
								{
									$this -> form_builider -> render = false;
									$form = $this -> form_builider -> create_form();
									$view = new Volta_Views($this -> render_form_view, $form);
								}
				
								if(isset($_POST['submit_form_sbt']))
								{
									try
									{
										if($this -> security -> csrf_check_token())
										{
											$valid = $this -> form_builider -> validate();
		
											if(!is_array($valid))
											{
												$this -> security -> filter_vars(true,true);
										
												if($this -> form_builider -> save($this -> table, null, array("token")))
												{
													if($this -> render_form_view === 'built-in')
														return $this -> err_code[400];
													else
													{
														$view -> set_message($this -> err_code[400]);
														header("Refresh: 1; URL=  index.php");
													}
												}
										
												else 
												{
													if($this -> render_form_view === 'built-in')
														return $this -> err_code[401];
													else
													{
														$view -> set_message($this -> err_code[401]);
														header("Refresh: 1; URL=  index.php");
													}
												}
											}
					
											else
											{
												if($this -> render_form_view == 'built-in')
													return $valid;
												else
													$view -> set_errors($valid);
											}
										}
									}
									
									catch(Volta_Admin_Generator_Csrf_Exception $e)
									{
										if($this -> render_panel_view == 'built-in')
											return $e -> getMessage();
										else
											$this -> panel_message = $e -> getMessage();
									}
								}
								
								return $view;
							}
						}
						
						catch(Volta_Acl_Deny_Exception $e)
						{
							if($this -> render_panel_view == 'built-in')
								return $e -> getMessage();
							else
								$this -> panel_message = $e -> getMessage();
						}
					}
			
					else if(isset($_GET['action']) && $action[0] != 'create' && $action[0] != 'update' && $action[0] != 'delete')
					{
						try
						{
							if($acl -> is_allowed($resource, $role))
							{
								$class = $resource;
			
								if(file_exists('actions/'.$class.'.php'))
									require_once('actions/'.$class.'.php');
								else
									throw new Volta_Admin_Generator_NoAction_Exception('Nie znaleziono pliku akcji: actions/' .$class.'.php');
					
								if(class_exists($class))
								{
									$action_object = new $class();
					
									$config = array(
													'table' => $this -> table,
													'where' => $this -> where_col,
													'relationship_table' => $this -> relation['table'],
													'rel_foreign_key' => $this -> relation['foreign_key'],
													'resource' => $resource,
													'action' => $role,
													'data' => $data
													);
													
									$action_object -> configure($config);
					
									if($action_object instanceof Action)
									{
										if(method_exists($action_object, $role))
											return $action_object -> $role();
										else
											return $action_object -> excecute();
									}
								}
				
								else
									throw new Volta_Admin_Generator_Exception('Nie znaleziono klasy: ' .$class);
							}
						}
						
						catch(Volta_Acl_Deny_Exception $e)
						{
							if($this -> render_panel_view == 'built-in')
								return $e -> getMessage();
							else
								$this -> panel_message = $e -> getMessage();
						}
					}
				}	
			}
			
			catch(Volta_Auth_Exception $e)
			{
				print $e -> getMessage();
			}
		}
	}
	
	/**
	*Zwraca nam tablice zawierajace wszystie info na temat stronnicowania
	*@access public 
	*@return array $this -> paginate zwraca tablice
	*/
	public function get_paginate()
	{
		$this -> paginate();
		return $this -> paginate;
	}

	/**
	*Wyswietla nam gotowe stronnicowanie
	*@access public 
	*@return string kod html stronnicowania
	*/
	public function paginate()
	{
	
		$url = explode("&", $_SERVER['QUERY_STRING']);
		foreach($url as $key => $query)
			if(strpos($query, 'page') !== false)
				unset($url[$key]);
					
		$this -> paginate['url'] = (isset($_GET['action'])) ? implode("&", $url).'&' : '';
		$this -> paginate['pages'] = ceil(($this -> paginate['count'] / $this -> paginate['per_page']));
		$this -> paginate['current'] = (isset($_GET['page'])) ? $_GET['page'] : 1;
		$this -> paginate['last'] = $this -> paginate['pages'];		
				
		if($this -> paginate['current'] < 1)
			$this -> paginate['current'] = 1;
		else if(($this -> paginate['current'] - 1) >= 1)
			$this -> paginate['prev'] = $this -> paginate['current'] - 1;
		else if(($this -> paginate['current'] - 1) === 1)
			$this -> paginate['prev'] = 0;
			
		if(($this -> paginate['current'] + 1) <= $this -> paginate['pages'])
			$this -> paginate['next'] = $this -> paginate['current'] + 1;
		else 
			$this -> paginate['next'] = 0;
				
		if(!$this -> nice_urls)
		{
			$html = '<table align="center"><tr><td>';
				
			if($this -> paginate['current'] > 1)
				$html .= '<a style="text-decoration:none;" href="?'.$this -> paginate['url'].'page='.$this -> paginate['first'].'"><<</a>';
				
			if($this -> paginate['prev'] > 0)
				$html .= '<a style="text-decoration:none;" href="?'.$this -> paginate['url'].'page='.$this -> paginate['prev'].'">'.$this -> paginate['prev'].'</a>';
					
			$html .= '<b>['.$this -> paginate['current'].']</b>';
					
			if($this -> paginate['next'] > 0)
				$html .= '<a style="text-decoration:none;" href="?'.$this -> paginate['url'].'page='.$this -> paginate['next'].'">'.$this -> paginate['next'].'</a>';
					
			if($this -> paginate['current'] < $this -> paginate['pages'])
				$html .= '<a style="text-decoration:none;" href="?'.$this -> paginate['url'].'page='.$this -> paginate['last'].'">>></a>';
				
			$html .= '</td></tr></table>';					
		}
				
		return $html;
	}
	
}

?>